package de.dnb.basics.utils;

import java.io.IOException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.marc4j.MarcXmlReader;
import org.marc4j.marc.DataField;
import org.marc4j.marc.Record;
import org.marc4j.marc.Subfield;
import org.marc4j.marc.VariableField;

import de.dnb.basics.Misc;
import de.dnb.basics.applicationComponents.RangeCheckUtils;
import de.dnb.basics.applicationComponents.StringUtils;

public final class PortalUtils {

	private PortalUtils() {
	}

	public static final String DNB_URI =
		"http://d-nb.info/(gnd/)?([-X0123456789]+)";
	public static final Pattern DNB_URI_PAT = Pattern.compile(DNB_URI);

	/**
	 * Liefert den Inhalt des Portaleintrags zur idn. Dabei ist es 
	 * erfreulicherweise egal, ob Titel- oder Normdatensatz, ob idn oder nid.
	 * 
	 * @param idn	nicht null, nicht leer
	 * @return		null, wenn nichts gefunden wurde
	 */
	public static String getRecordViaPortal(final String idn) {
		RangeCheckUtils.assertStringParamNotNullOrEmpty("idn", idn);
		//String uri = "http://d-nb.info/" + idn;
		String uri =
			"https://portal.dnb.de/opac.htm?" + "method=simpleSearch"
				+ "&cqlMode=true" + "&query=idn%3D" + idn;
		return Misc.getWebsite(uri);
	}

	/**
	 * Liefert den Inhalt des Portaleintrags zur idn. Dabei ist es 
	 * erfreulicherweise egal, ob Titel- oder Normdatensatz, ob idn oder nid.
	 * 
	 * @param idn	nicht null, nicht leer
	 * @return		null, wenn nichts gefunden wurde
	 */
	public static String getDNBrdf(final String idn) {
		RangeCheckUtils.assertStringParamNotNullOrEmpty("idn", idn);
		String uri = "http://d-nb.info/" + idn + "/about/rdf";
		return Misc.getWebsite(uri);
	}

	/**
	 * Liefert die MARC-21-XML-Darstellung der idn. Dabei ist es 
	 * erfreulicherweise egal, ob Titel- oder Normdatensatz, ob idn oder nid.
	 * 
	 * @param idn	nicht null, nicht leer
	 * @return		null, wenn nichts gefunden wurde
	 */
	public static String getMARC21xml(final String idn) {
		RangeCheckUtils.assertStringParamNotNullOrEmpty("idn", idn);
		String uri =
			"https://portal.dnb.de/opac.htm?method=requestMarcXml&idn=" + idn;
		return Misc.getWebsite(uri);
	}

	/**
	 * Liefert einen Marc-Record (marc4j) zu einer idn über das Portal.
	 * 
	 * @param idn 	beliebig
	 * @return		Gültigen Record oder null
	 */
	public static Record getMarcRecord(final String idn) {
		URL url;
		Record record = null;
		//		try {
		//			url =
		//				new URL("https://portal.dnb.de/opac.htm?"
		//					+ "method=requestMarcXml&idn=" + idn);
		//			MarcXmlReader reader = new MarcXmlReader(url.openStream());
		//			if (reader.hasNext()) {
		//				record = reader.next();
		//			}
		//		} catch (IOException e) {
		//			
		//		}
		if (record == null)
			try {
				url = new URL("http://d-nb.info/" + idn + "/about/marcxml");
				MarcXmlReader reader = new MarcXmlReader(url.openStream());
				if (reader.hasNext()) {
					record = reader.next();
				}
			} catch (IOException e) {

			}
		return record;

	}

	/**
	 * Findet die IDN. Das ist bei Titeldaten die eingegebene Idn,
	 * bei Normdaten kann sie abweichen.
	 * 
	 * @param idn	nicht null.
	 * @return			null, wenn keine Verbindung zum Portal aufgebaut
	 * 					werden konnte oder wenn keine gültige idn
	 * 					vorlag.   
	 */
	public static String getDNBidn(final String idn) {
		RangeCheckUtils.assertReferenceParamNotNull("idn", idn);
		String rec = getRecordViaPortal(idn);
		Matcher m = PortalUtils.DNB_URI_PAT.matcher(rec);
		if (m.find())
			return m.group(2);
		return null;
	}

	/**
	 * Findet die URI. 
	 * 
	 * @param idn	nicht null.
	 * @return			null, wenn keine Verbindung zum Portal aufgebaut
	 * 					werden konnte oder wenn keine gültige idn
	 * 					vorlag.   
	 */
	public static String getDNBuri(final String idn) {
		RangeCheckUtils.assertReferenceParamNotNull("idn", idn);
		// Schnellere Methode, funktioniert nicht immer:
		Record record = getMarcRecord(idn);
		if (record != null) {
			DataField field = (DataField) record.getVariableField("024");
			if (field != null){
				Subfield subf = field.getSubfield('a');
				String data = subf.getData();
				if (data.contains("http://"))
					return data;
			}
		}
		// langsame und sichere Methode:
		String rec = getRecordViaPortal(idn);
		Matcher m = PortalUtils.DNB_URI_PAT.matcher(rec);
		if (m.find())
			return m.group();
		return null;
	}

	public static void main(String[] args) {
		String idn = StringUtils.readClipboard();
		;
		System.out.println(getDNBuri(idn));
	}

}
